<?php

namespace KukePay\Tencent\Unifiedorder;

use GuzzleHttp\Client;
use KukePay\ExceptionHandler;
use KukePay\Tencent\Kernel\RequestFactory;
use KukePay\Tencent\Kernel\SignFactory;

class Application
{
    private $app_id;
    private $mch_id;
    private $key;
    private $uri = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    private $request;
    private $sign;
    private static $interface;

    /**
     * @param $config
     * @return Application
     */
    public static function getInterface($config)
    {
        if (!isset(self::$interface)) {
            self::$interface = new self($config);
        }
        return self::$interface;
    }

    /**
     * Factory constructor.
     * @param array $config
     */
    private function __construct(array $config)
    {
        foreach ($config as $key => $value) {
            $this->{$key} = $value;
        }
        $this->request = RequestFactory::getInterface();

        $this->sign = SignFactory::getInterface();
    }

    /**
     * 防止元素被克隆
     */
    private function __clone(){}

    /**
     * @param array $params
     * @param string $trade_type
     * @param callable $function
     * @return string
     */
    public function send(array $params, string $trade_type, callable $function)
    {
        try {
            $unified = [
                'appid' => $this->app_id,
                'attach' => 'pay',             //商家数据包，原样返回，如果填写中文，请注意转换为utf-8
                'mch_id' => $this->mch_id,
                'nonce_str' => $this->sign->createNonceStr(),
                'trade_type' => $trade_type,
            ];

            foreach ($params as $key => $value) {
                $unified[$key] = $value;
            }

            $unified['sign'] = $this->sign->getSign($unified, $this->key);
            //curl
            $response = $this->request->client->post($this->uri, [
                'body' => $this->sign->arrayToXml($unified)
            ])->getBody()->getContents();

            libxml_disable_entity_loader(true);
            $unifiedOrder = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA);

            if ($unifiedOrder === false) throw new ExceptionHandler('parse xml error');

            if ($unifiedOrder->return_code != 'SUCCESS') throw new ExceptionHandler($unifiedOrder->return_msg);

            if ($unifiedOrder->result_code != 'SUCCESS') throw new ExceptionHandler($unifiedOrder->err_code_des);

            return $function($unifiedOrder, $this);


        } catch (ExceptionHandler $exception) {
            return $exception->getMessage();
        } catch (\Exception $exception) {
            return $exception->getMessage();
        }
    }

    /**
     * 二次签名获取参数
     * @param $unifiedOrder
     * @return array
     */
    public function getParams($unifiedOrder)
    {
        $arr = [
            "appId" => $this->app_id,
            "timeStamp" => time(),
            "nonceStr" => $this->sign->createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => 'MD5'
        ];

        $arr['paySign'] = $this->sign->getSign($arr, $this->key);

        return $arr;
    }
}